Retrofit是專為API連線而生的第三方套件,與API連線的效率非常高,最特別的是其規範的REST框架讓程式高度解耦,好寫易維護,被譽為API連線的教科書。另外它跟OkHttp同為Square公司出品,兩者可以完美整合發揮更多功能。
然而對於像我這樣基礎知識低落的廢物來說,官網說明我當初真的看不懂,額外看了好多資料兜了一大圈才了解它的用法,但只要成功用一次之後就會發現它其實不難,希望透過今天的程式範例可以讓大家快速上手使用。
(連線處理時間比較表,可以看出Retrofit比AsyncTask快非常多,資料來源:http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit/ )
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
第一行是Retrofit本體,第二行是用Google的Gson套件作為資料處理的converter,Retrofit都整合好了所以我們之後只要一行程式碼就能用Gson處理資料
在AndroidManifet.xml加入,可參考Day23有圖解
<uses-permission android:name="android.permission.INTERNET" />
Retrofit會自動將連線取得的資料轉成物件便於做後續處理,以我們的測試資料(https://jsonplaceholder.typicode.com/albums/1 )來說,有userId, id, title三個欄位,我們就建一個Albums物件如下,注意欄位名稱要跟API裡的一致哦
public class Albums {
private int userId;
private int id;
private String title;
public Albums(int userId, int id, String title) {
this.userId = userId;
this.id = id;
this.title = title;
}
public int getUserId() {
return userId;
}
public int getId() {
return id;
}
public String getTitle() {
return title;
}
}
Interface就是各個連線的接口,每個連線是用GET或POST及其路徑、參數都寫在這裡,個人覺得是Retrofit的精華,將所有連線統一管理。
// 注意是interface而不是class哦
public interface MyAPIService {
// 測試網站 https://jsonplaceholder.typicode.com/
// GET網址 https://jsonplaceholder.typicode.com/albums/1
// POST網址 https://jsonplaceholder.typicode.com/albums
// ...typicode.com/[這裡就是API的路徑]
@GET("albums/1") // 設置一個GET連線,路徑為albums/1
Call<Albums> getAlbums(); // 取得的回傳資料用Albums物件接收,連線名稱取為getAlbums
@GET("albums/{id}") // 用{}表示路徑參數,@Path會將參數帶入至該位置
Call<Albums> getAlbumsById(@Path("id") int id);
@POST("albums") // 用@Body表示要傳送Body資料
Call<Albums> postAlbums(@Body Albums albums);
}
測試網址的POST是用Body方式收參數所以我們用@Body,若是要用問號帶在網址後的參數如?id=1則應改用@Query
建立連線的基底,在此設置連線網站和converter,注意是網站哦!以測試資料來說網站為
https://jsonplaceholder.typicode.com/ ,後面API連線的albums/1那些是寫在interface裡
public class RetrofitManager {
// 以Singleton模式建立
private static RetrofitManager mInstance = new RetrofitManager();
private MyAPIService myAPIService;
private RetrofitManager() {
// 設置baseUrl即要連的網站,addConverterFactory用Gson作為資料處理Converter
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
myAPIService = retrofit.create(MyAPIService.class);
}
public static RetrofitManager getInstance() {
return mInstance;
}
public MyAPIService getAPI() {
return myAPIService;
}
}
到這邊就建立完成,可以開始使用囉。
(若昨天有用OkHttp練習的話,今天改用Retrofit要將程式最上面import中OkHttp的部分先去掉喔)
操作步驟:
public class MainActivity extends AppCompatActivity {
// 1. 宣告MyAPIService
MyAPIService myAPIService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 2. 透過RetrofitManager取得連線基底
myAPIService = RetrofitManager.getInstance().getAPI();
// 3. 建立連線的Call,此處設置call為myAPIService中的getAlbums()連線
Call<Albums> call = myAPIService.getAlbums();
// 4. 執行call
call.enqueue(new Callback<Albums>() {
@Override
public void onResponse(Call<Albums> call, Response<Albums> response) {
// 連線成功
// 回傳的資料已轉成Albums物件,可直接用get方法取得特定欄位
String title = response.body().getTitle();
Log.d("title", title);
}
@Override
public void onFailure(Call<Albums> call, Throwable t) {
// 連線失敗
}
});
}
}
若要用Interface中的第二個GET方式getAlbumsById,只要改call那行的method並將參數傳入就可以了
Call<Albums> call = myAPIService.getAlbumsById(2);
call.enqueue(new Callback<Albums>() {
// 略..
});
POST時測試網址須用Body的形式傳送,我們已經在Interface裡設定好了,只要建一個Albums物件作為Body送出就可以了。
// 建立要POST的物件
Albums albums = new Albums(1, 1, "Castle on the Hill");
// 將物件作為postAlbums的參數
Call<Albums> call = myAPIService.postAlbums(albums);
// 執行call
call.enqueue(new Callback<Albums>() {
// 略..
});
Retrofit的連線基底可設置的功能不像OkHttp那麼多,但沒關係,兩者師出同門,可以直接把OkHttpClient整碗拿過來用,只要在RetrofitManager中加入就可以了
我們把昨天的OkHttpClient直接拿來用,會幫我們印出連線Log,此外再多加入連線Timeout時間,當連線30秒還未成功就放棄
private RetrofitManager() {
// 建立OkHttpClient
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(30, TimeUnit.SECONDS) // 設置連線Timeout
.addInterceptor(new HttpLoggingInterceptor().setLevel(Level.BASIC))
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient) // 將okHttpClient加入連線基底
.build();
myAPIService = retrofit.create(MyAPIService.class);
}
此外像OkHttp的Request、FormBody等部分Retrofit也都可以用,兩者的整合度非常高,當您需要什麼功能而Retrofit沒有時,可以到OkHttp找找看並直接拿過來。
Retrofit作為當今API連線的首選,個人覺得它的學習門檻比較高一點點,用Interface和註解的方式讓我當時一看就迷惘了,折騰好一陣子才成功把專案轉成Retrofit架構。希望今天的文章可以讓大家比較好了解上手,如果還是看不懂也沒關係,請去看其他大大的文章不要就此放棄XD。
明天介紹同為Square公司出品的圖片讀取套件Picasso,用於處理網路圖片時非常方便,而且程式碼超級簡潔,明天看就知道囉。
請問API回傳不是字串而是陣列的話該怎麼處理呢
EX:
data:[{
id:1
name:"李"
,
id:2
name:"王"}]
public class xxxx {
private data data;//get&建構一樣要設
}
public class data{
private int id;//get&建構一樣要設
private String name;//get&建構一樣要設
}
這我也走了很多彎路你可以參考 這更詳細
https://stackoverflow.com/questions/50422313/read-json-nested-array-response-to-avoid-duplicate-entries-in-android